package middleware

import (
	"net/http"
	"rego-top/dto"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
)

var validate *validator.Validate

func init() {
	validate = validator.New()
}

// ValidateJSON 验证JSON请求体的中间件
func ValidateJSON(obj interface{}) gin.HandlerFunc {
	return func(c *gin.Context) {
		if err := c.ShouldBindJSON(obj); err != nil {
			var validationErrors []dto.ValidationError
			
			if validatorErrors, ok := err.(validator.ValidationErrors); ok {
				for _, validatorError := range validatorErrors {
					validationError := dto.ValidationError{
						Field:   validatorError.Field(),
						Message: getValidationErrorMessage(validatorError),
					}
					validationErrors = append(validationErrors, validationError)
				}
			} else {
				// 其他类型的错误（如JSON格式错误）
				validationErrors = append(validationErrors, dto.ValidationError{
					Field:   "request",
					Message: "请求格式错误: " + err.Error(),
				})
			}
			
			c.JSON(http.StatusBadRequest, dto.ErrorResponse("参数验证失败", validationErrors))
			c.Abort()
			return
		}
		
		c.Set("validated_data", obj)
		c.Next()
	}
}

// getValidationErrorMessage 获取验证错误消息
func getValidationErrorMessage(err validator.FieldError) string {
	switch err.Tag() {
	case "required":
		return "此字段为必填项"
	case "email":
		return "请输入有效的邮箱地址"
	case "min":
		return "长度不能少于 " + err.Param() + " 个字符"
	case "max":
		return "长度不能超过 " + err.Param() + " 个字符"
	case "len":
		return "长度必须为 " + err.Param() + " 个字符"
	case "numeric":
		return "必须为数字"
	case "alpha":
		return "只能包含字母"
	case "alphanum":
		return "只能包含字母和数字"
	case "url":
		return "请输入有效的URL"
	case "uri":
		return "请输入有效的URI"
	case "base64":
		return "必须为有效的Base64编码"
	case "contains":
		return "必须包含 " + err.Param()
	case "containsany":
		return "必须包含以下字符之一: " + err.Param()
	case "excludes":
		return "不能包含 " + err.Param()
	case "excludesall":
		return "不能包含以下任何字符: " + err.Param()
	case "excludesrune":
		return "不能包含字符 " + err.Param()
	case "lowercase":
		return "必须为小写字母"
	case "uppercase":
		return "必须为大写字母"
	case "datetime":
		return "必须为有效的日期时间格式"
	case "timezone":
		return "必须为有效的时区"
	case "uuid":
		return "必须为有效的UUID格式"
	case "uuid3":
		return "必须为有效的UUID v3格式"
	case "uuid4":
		return "必须为有效的UUID v4格式"
	case "uuid5":
		return "必须为有效的UUID v5格式"
	case "ascii":
		return "只能包含ASCII字符"
	case "printascii":
		return "只能包含可打印的ASCII字符"
	case "multibyte":
		return "必须包含多字节字符"
	case "datauri":
		return "必须为有效的数据URI"
	case "latitude":
		return "必须为有效的纬度"
	case "longitude":
		return "必须为有效的经度"
	case "ssn":
		return "必须为有效的社会保障号码"
	case "hexadecimal":
		return "必须为十六进制格式"
	case "hexcolor":
		return "必须为有效的十六进制颜色代码"
	case "rgb":
		return "必须为有效的RGB颜色"
	case "rgba":
		return "必须为有效的RGBA颜色"
	case "hsl":
		return "必须为有效的HSL颜色"
	case "hsla":
		return "必须为有效的HSLA颜色"
	case "color":
		return "必须为有效的颜色格式"
	case "json":
		return "必须为有效的JSON格式"
	case "jwt":
		return "必须为有效的JWT令牌"
	case "html":
		return "不能包含HTML标签"
	case "html_encoded":
		return "必须为HTML编码格式"
	case "url_encoded":
		return "必须为URL编码格式"
	case "dir":
		return "必须为有效的目录路径"
	case "file":
		return "必须为有效的文件路径"
	case "base64url":
		return "必须为有效的Base64 URL编码"
	case "isbn":
		return "必须为有效的ISBN"
	case "isbn10":
		return "必须为有效的ISBN-10"
	case "isbn13":
		return "必须为有效的ISBN-13"
	case "eth_addr":
		return "必须为有效的以太坊地址"
	case "btc_addr":
		return "必须为有效的比特币地址"
	case "btc_addr_bech32":
		return "必须为有效的比特币Bech32地址"
	case "credit_card":
		return "必须为有效的信用卡号"
	case "mongodb":
		return "必须为有效的MongoDB ObjectID"
	case "cron":
		return "必须为有效的Cron表达式"
	case "spicedb":
		return "必须为有效的SpiceDB格式"
	default:
		return "字段验证失败: " + err.Tag()
	}
}

// GetValidatedData 从上下文中获取验证后的数据
func GetValidatedData(c *gin.Context) (interface{}, bool) {
	if data, exists := c.Get("validated_data"); exists {
		return data, true
	}
	return nil, false
}

// ValidateQueryParams 验证查询参数的中间件
func ValidateQueryParams(requiredParams []string) gin.HandlerFunc {
	return func(c *gin.Context) {
		var missingParams []string
		
		for _, param := range requiredParams {
			if value := c.Query(param); value == "" {
				missingParams = append(missingParams, param)
			}
		}
		
		if len(missingParams) > 0 {
			c.JSON(http.StatusBadRequest, dto.ErrorResponse(
				"缺少必需的查询参数", 
				"缺少参数: "+strings.Join(missingParams, ", "),
			))
			c.Abort()
			return
		}
		
		c.Next()
	}
}

// ValidatePathParams 验证路径参数的中间件
func ValidatePathParams(requiredParams []string) gin.HandlerFunc {
	return func(c *gin.Context) {
		var missingParams []string
		
		for _, param := range requiredParams {
			if value := c.Param(param); value == "" {
				missingParams = append(missingParams, param)
			}
		}
		
		if len(missingParams) > 0 {
			c.JSON(http.StatusBadRequest, dto.ErrorResponse(
				"缺少必需的路径参数", 
				"缺少参数: "+strings.Join(missingParams, ", "),
			))
			c.Abort()
			return
		}
		
		c.Next()
	}
}